<template>
    <admin-module id="perm_management" v-loading="loading">
        <template slot="header">
            <el-form size="small" inline label-position="left" label-width="70px" @submit.native.prevent>
                <el-form-item label="权限名称">
                    <el-input placeholder="根据权限名称搜索" clearable v-model="whereForm.keyword"></el-input>
                </el-form-item>
                <el-form-item label="创建时间">
                    <el-date-picker type="daterange" align="right" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" v-model="whereForm.dateRange"> </el-date-picker>
                </el-form-item>
                <el-form-item label-width="0px">
                    <el-button type="primary" size="small" icon="el-icon-search" native-type="submit" @click="handleSearch">搜索</el-button>
                </el-form-item>
            </el-form>
        </template>
        <template slot="action">
            <el-button type="primary" size="small" icon="el-icon-plus" @click="handleCreate">添加</el-button>
            <el-button type="danger" size="small" icon="el-icon-delete" :disabled="!isSelectedRows" @click="handleDeleteMulti">删除</el-button>
            <el-button type="default" size="small" icon="el-icon-refresh-right" @click="handleReload" :loading="loading" :disabled="loading">{{ loading ? "刷新中" : "刷新" }}</el-button>
        </template>
        <template>
            <el-table :data="tableData" stripe="" empty-text="暂未添加任何权限" @selection-change="handleSelectedRows" :max-height="maxHeight" row-key="id" :tree-props="{ children: 'children' }">
                <el-table-column type="selection" width="50" align="center" fixed="left"></el-table-column>
                <el-table-column label="权限名称" width="150" prop="name" sortable="" :formatter="notEmpty"></el-table-column>
                <el-table-column label="图标" align="center" width="100" prop="icon" sortable="" :formatter="notEmpty">
                    <template slot-scope="scope">
                        <i :class="scope.row.icon"></i>
                    </template>
                </el-table-column>
                <el-table-column label="访问路径" min-width="200" prop="path" sortable="" :formatter="notEmpty"></el-table-column>
                <el-table-column label="权限节点" width="240" prop="perm" sortable="" :formatter="notEmpty"></el-table-column>
                <el-table-column label="排序号" width="100" align="center" prop="sort" sortable="" :formatter="notEmpty"> </el-table-column>
                <el-table-column label="类型" width="100" align="center" prop="type" sortable="">
                    <template slot-scope="scope">
                        <span style="color: blue" v-if="scope.row.type == 1">分组</span>
                        <span style="color: green" v-if="scope.row.type == 2">菜单</span>
                        <span style="color: orange" v-if="scope.row.type == 3">动作</span>
                    </template>
                </el-table-column>
                <el-table-column label="是否启用" width="100" align="center" prop="status" sortable="" :formatter="notEmpty">
                    <template slot-scope="scope">
                        <el-switch v-model="scope.row.status" :active-value="1" :inactive-value="0" @change="(data) => handleChangeStatus(data, scope.row)"></el-switch>
                    </template>
                </el-table-column>
                <el-table-column label="创建时间" width="200" prop="create_time" align="center" sortable="" :formatter="notEmpty"> </el-table-column>
                <el-table-column label="更新时间" width="200" prop="update_time" align="center" sortable="" :formatter="notEmpty"> </el-table-column>
                <el-table-column label="操作" width="200" fixed="right" align="center" :formatter="notEmpty">
                    <template slot-scope="scope">
                        <el-button-group>
                            <el-button size="mini" round type="primary" @click="handleEdit(scope.row)">修改</el-button>
                            <el-button size="mini" round type="danger" @click="handleDelete(scope.row)">删除</el-button>
                        </el-button-group>
                    </template>
                </el-table-column>
            </el-table>
            <el-dialog :title="dialogFormTitle" :visible.sync="showDialogForm" width="720px" :close-on-click-modal="false">
                <el-form label-position="left" label-width="80px" @submit.native.prevent :rules="rules" ref="form" :model="form">
                    <el-row :gutter="20">
                        <el-col :span="12">
                            <el-form-item :label="appendPrefix('名称')" prop="name">
                                <el-input type="text" placeholder="请输入权限名称" clearable="" v-model="form.name"></el-input>
                            </el-form-item>
                        </el-col>
                        <el-col :span="12">
                            <el-form-item :label="appendPrefix('图标')">
                                <icon-selected v-model="form.icon" :disabled="form.type == 3"></icon-selected>
                            </el-form-item>
                        </el-col>
                        <el-col :span="12">
                            <el-form-item :label="appendPrefix('节点')">
                                <el-tooltip content="可自由设计,也可参考官方默认配置方式" placement="top-start">
                                    <el-input type="text" placeholder="请输入权限节点" clearable="" v-model="form.perm"></el-input>
                                </el-tooltip>
                            </el-form-item>
                        </el-col>
                        <el-col :span="12">
                            <el-form-item label="排序号">
                                <el-tooltip content="数字越大越靠前显示" placement="top-start">
                                    <el-input-number v-model="form.sort" placeholder="排序号"></el-input-number>
                                </el-tooltip>
                            </el-form-item>
                        </el-col>
                        <el-col :span="12">
                            <el-form-item :label="appendPrefix('类型')">
                                <el-radio-group v-model="form.type">
                                    <el-tooltip content="即后台左侧菜单栏分组,仅用于显示不可鉴权" placement="top-start">
                                        <el-radio :label="1">分组</el-radio>
                                    </el-tooltip>
                                    <el-tooltip content="即后台左侧菜单栏功能模块,可鉴权" placement="top-start">
                                        <el-radio :label="2">菜单</el-radio>
                                    </el-tooltip>
                                    <el-tooltip content="即某个功能模块的增删改查操作,可鉴权" placement="top-start">
                                        <el-radio :label="3">动作</el-radio>
                                    </el-tooltip>
                                </el-radio-group>
                            </el-form-item>
                        </el-col>
                        <el-col :span="12">
                            <el-form-item label="打开方式">
                                <el-radio-group v-model="form.target" :disabled="form.type != 3">
                                    <el-tooltip content="默认值" placement="top-start">
                                        <el-radio label="_self">当前窗口</el-radio>
                                    </el-tooltip>
                                    <el-tooltip content="仅对菜单有效, 一般用于链接外部地址" placement="top-start">
                                        <el-radio label="_blank">新窗口打开</el-radio>
                                    </el-tooltip>
                                </el-radio-group>
                            </el-form-item>
                        </el-col>
                    </el-row>
                    <el-form-item label="路由地址" v-if="form.type == 2">
                        <el-tooltip content="仅在权限类型为菜单时有效" placement="top-start">
                            <el-input type="text" placeholder="请输入权限名称" clearable="" v-model="form.path"></el-input>
                        </el-tooltip>
                    </el-form-item>
                    <el-form-item :label="appendPrefix('介绍')">
                        <el-input type="textarea" placeholder="请输入权限介绍" clearable="" :rows="5" v-model="form.remark"></el-input>
                    </el-form-item>
                    <el-form-item label="隶属于">
                        <div class="selected-perm">
                            <el-tree empty-text="暂无数据" :data="permTree" show-checkbox node-key="id" :props="treeProps" ref="tree" :check-strictly="true" default-expand-all @check-change="handleNodeClick"></el-tree>
                        </div>
                    </el-form-item>
                    <el-form-item>
                        <el-button type="primary" native-type="submit" @click="handleSave">保存{{ formatTypeName }}</el-button>
                    </el-form-item>
                </el-form>
            </el-dialog>
        </template>
    </admin-module>
</template>

<script>
import { cloneDeep } from "lodash";

export default {
    data() {
        return {
            // 表格最大高度
            maxHeight: document.documentElement.clientHeight - 275,
            // 是否在加载中
            loading: false,
            // 权限树
            permTree: [],
            treeProps: {
                children: "children",
                label: "name",
            },
            // 表格数据
            tableData: [],
            // 当前操作行数据
            form: {},
            // 表单校验规则
            rules: {
                name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
            },
            // 是否显示模态框
            showDialogForm: false,
            showDialogPerm: false,
            // 选中行数据
            selectedRows: [],
            // 过滤条件
            whereForm: {
                keyword: "",
                dateRange: [],
            },
        };
    },
    created() {
        this.getData();
    },
    computed: {
        // 获取类型名称
        formatTypeName() {
            const { type } = this.form;

            if (type == 1) return "分组";
            if (type == 2) return "菜单";
            if (type == 3) return "动作";

            return type;
        },
        // 行数据是否有id,用于区分是新建还是修改
        hasRowId() {
            const { form } = this;
            return form.id ? true : false;
        },
        // 模态框标题
        dialogFormTitle() {
            const { hasRowId, formatTypeName } = this;

            return (hasRowId ? "修改" : "添加") + formatTypeName;
        },
        // 选择的行数据
        isSelectedRows() {
            const { selectedRows } = this;

            return selectedRows.length > 0;
        },
        // 选择的行数据id
        selectedRowsIds() {
            const { selectedRows } = this;

            const ids = [];

            for (const row of selectedRows) {
                ids.push(row.id);
            }

            return ids;
        },
        // 关键词
        keyword() {
            return this.whereForm.keyword;
        },
    },
    watch: {
        keyword(keyword) {
            if (!keyword) this.getData();
        },
    },
    methods: {
        /**
         * 表单内添加前缀
         */
        appendPrefix(name) {
            return this.formatTypeName + name;
        },
        /**
         * 渲染父类树
         * @param {array} ids 权限id 支持多个
         */
        renderPermTree(ids = []) {
            this.$refs.tree.setCheckedKeys([]);
            this.$nextTick(() => {
                for (let i = 0; i < ids.length; i++) {
                    const id = ids[i];
                    const node = this.$refs.tree.getNode(id);
                    this.$refs.tree.setChecked(node, true);
                }
            });
        },
        /**
         * 树形结构单选逻辑
         */
        handleNodeClick(data, checked, node) {
            if (checked === true) {
                this.checkedId = data.id;
                this.$refs.tree.setCheckedKeys([data.id]);
            } else {
                if (this.checkedId == data.id) {
                    this.$refs.tree.setCheckedKeys([data.id]);
                }
            }
        },
        /**
         * 获取权限树
         */
        getPermTree() {
            this.$get("/perm_management/permTree").then((res) => {
                const { code, data } = res;
                if (code == 200) {
                    const root = {
                        id: 0,
                        name: "根节点",
                    };
                    this.permTree = cloneDeep([root].concat(data));
                }
            });
        },
        /**
         * 改变启用状态
         */
        handleChangeStatus(value, row) {
            const { id, status } = row;

            this.$post("/perm_management/update", { id, status }).then((res) => {
                const { msg, code } = res;
                if (code === 200) this.getData();
            });
        },
        /**
         * 搜索
         */
        handleSearch() {
            this.getData();
        },
        /**
         * 当选中行
         * @param {array} rows 选中行数据
         */
        handleSelectedRows(rows) {
            this.selectedRows = cloneDeep(rows);
        },
        /**
         * 表单数据初始化
         */
        resetForm() {
            this.form = {
                name: "",
                remark: "",
                sort: 0,
                pid: 0,
                type: 1,
                target: "_self",
                icon: "",
                path: "",
            };
        },
        /**
         * 移除行数据
         * @param {array} ids 行数据id,支持多个id
         */
        removeRow(ids = []) {
            if (Object.prototype.toString.call(ids) === "[object Array]") ids = ids.join(",");

            return this.$post("/perm_management/remove", { id: ids });
        },
        /**
         * 检查数据是否为空,如果空就返回 value
         */
        notEmpty(row, col, value, index) {
            return value || "-";
        },
        /**
         * 提交表单
         */
        handleSave() {
            this.$refs.form.validate((valid) => {
                if (valid) {
                    const nodes = this.$refs.tree.getCheckedNodes(false, true);
                    const form = cloneDeep(this.form);
                    form.pid = nodes[0].id || 0;

                    if (form.id) {
                        this.$post("/perm_management/update", form).then((res) => {
                            const { msg, code } = res;

                            if (code === 200) {
                                this.showDialogForm = false;
                                this.getData();
                            }
                        });
                    } else {
                        this.$post("/perm_management/create", form).then((res) => {
                            const { msg, code } = res;

                            if (code === 200) {
                                this.showDialogForm = false;
                                this.getData();
                            }
                        });
                    }
                } else {
                    return false;
                }
            });
        },
        /**
         * 当修改的时候
         */
        handleEdit(data) {
            this.resetForm();
            this.form = cloneDeep(data);
            this.showDialogForm = true;
            this.$nextTick(() => {
                this.renderPermTree([data.pid]);
            });
        },
        /**
         * 当删除的时候
         */
        handleDelete(data) {
            this.$confirm("是否要删除该数据? ", "删除确认", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning",
            })
                .then(() => {
                    this.removeRow(data.id).then((res) => {
                        if (res.code == 200) {
                            this.$message({
                                type: "success",
                                message: "删除成功!",
                            });
                            this.getData();
                        }
                    });
                })
                .catch(() => {});
        },
        /**
         * 批量删除
         */
        handleDeleteMulti() {
            this.$confirm("是否要删除选中的数据? ", "删除确认", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning",
            })
                .then(() => {
                    const { selectedRowsIds } = this;

                    this.removeRow(selectedRowsIds).then((res) => {
                        if (res.code == 200) {
                            this.$message({
                                type: "success",
                                message: "删除成功!",
                            });
                            this.getData();
                        }
                    });
                })
                .catch(() => {});
        },
        /**
         * 当刷新的时候
         */
        handleReload() {
            this.getData().then(() => {
                this.$message.success("刷新成功");
            });
        },
        /**
         * 当创建的时候
         */
        handleCreate() {
            this.resetForm();
            this.showDialogForm = true;
            this.$nextTick(() => {
                this.renderPermTree([0]);
            });
        },
        /**
         * 获取数据
         */
        getData() {
            return new Promise((resolve, reject) => {
                const { keyword, dateRange } = this.whereForm;

                const form = {};

                if (keyword) form.keyword = keyword;

                if (dateRange && dateRange.length == 2) {
                    form.startTime = dateRange[0];
                    form.endTime = dateRange[1];
                }

                this.loading = true;
                this.$get("/perm_management/list", { params: form })
                    .then((res) => {
                        this.loading = false;
                        const { code, msg, data } = res;
                        if (code === 200) {
                            this.tableData = cloneDeep(data);
                            resolve();
                        } else {
                            reject(new Error(msg));
                        }
                        this.getPermTree();
                    })
                    .catch((err) => {
                        this.loading = false;
                        this.getPermTree();
                        reject(err);
                    });
            });
        },
    },
};
</script>

<style lang="scss" scoped>
#perm_management {
    .selected-perm {
        padding: 4px 0px;
        max-height: 200px;
        overflow-y: auto;
        background-color: #f6f6f6;
        border-radius: 3px;
        box-shadow: 0px 1px 5px rgba($color: #000000, $alpha: 0.1) inset;

        .el-tree {
            background-color: transparent;

            ::v-deep .el-tree-node__content:hover {
                background-color: transparent;
            }
        }
    }
}
</style>
